#ifndef NUM_POOL_H
#define NUM_POOL_H

#include <inttypes.h>

namespace usnet {
class NumPool {
public:
    ~NumPool();
    NumPool(const uint32_t nbits);
    int64_t GetNumber();
    bool GetNumber(const uint32_t num);
    void PutNumber(const uint32_t num);

private:
    enum TableSize : uint32_t {
        MIN_NUM_BITS = 6,
        MAX_NUM_BITS = 32,
        TAB_UNI_BITS = 6,
        MIN_TAB_SIZE = 1,
        BIT_OFF_MASK = 0x3f,
    };

    struct BitPosition {
        BitPosition(const uint32_t num):
            idx_ { num >> TAB_UNI_BITS },
            off_ { num & BIT_OFF_MASK }
        {
            // nothing to do
        }

        inline int64_t GetValue() const
        {
            return (idx_ << TAB_UNI_BITS) + off_;
        }

        inline bool operator<(const BitPosition& pos) const
        {
            return GetValue() < pos.GetValue();
        }

        inline bool operator==(const BitPosition& pos) const
        {
            if (idx_ != pos.idx_) {
                return false;
            }
            if (off_ != pos.off_) {
                return false;
            }
            return true;
        }

        inline BitPosition& operator=(const BitPosition& pos)
        {
            idx_ = pos.idx_;
            off_ = pos.off_;
            return (*this);
        }

        uint32_t idx_ { 0 };
        uint32_t off_ { 0 };
    };

    const uint32_t max_num_ { 0 };
    const uint32_t max_tab_size_ { MIN_TAB_SIZE };
    BitPosition min_free_num_ { 0 };
    BitPosition max_used_num_ { 0 };
    uint32_t cur_tab_size_ { MIN_TAB_SIZE };
    struct {
        uint64_t  min_tab_[MIN_TAB_SIZE] { };
        uint64_t* cur_tab_ { min_tab_ };
    } num_tab_;
};
} // end of namespace usnet
#endif